package Commnads;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.Executor;

import DB.DataBase;

/**
 * From this class we execute the commands that had initiated by the GUI (or from the CLI).
 * we call to the command from class {@link Commands}, that contain all the commands
 * each command had been executed in each thread by the {@link Executor}
 * @author DROR
 */

public class GuiCommands 
{
	private Commands commands;
	
	/**
	 * Constructor
	 * @param com reference to {@link Commands} class
	 */
	public GuiCommands(Commands com) 
	{
		commands= com;
	}
	
	/** 
	 * This function returns the Executor
	 * @return  {@link Executor} The executor from {@link Commands} class
	 */
	public Executor getExecutor()
	{
		return commands.getExecutor();
	}
	
	/**
	 * This function calculate the percent of the tagged files for updating the progress bar 
	 * We call to that function from Listening class (via Commands class)
	 * @return The percent
	 */
	public int getPercent()
	{
		return commands.getPercent();
	}
	
	/**
	 * This function inserts all the algorithms to the {@link HashMap}
	 * @param alg {@link String} the name of algorithm
	 * @param path {@link String} algorithm's path
	 */
	public void insertToAllAlgos(String alg,String path)	
	{
		commands.insertToAllAlgos(alg,path);
	}
	
	/**
	 * This function returns all the algorithms from DB
	 * @return an {@link ArrayList} of  all algorithms in DB
	 */
	public ArrayList<String> getAllAlgos()
	{
		Commands.getAllAlgos c = (Commands.getAllAlgos)commands.getCom("get all algos");
		c.execute();
		return c.getAlgosArr();
	}
	
	/**
	 * This function returns only the selected algorithms from DB
	 * @return an {@link ArrayList} of selected algorithms from DB
	 */
	public ArrayList<String> getSelectedAlgos()
	{
		Commands.getSelectedAlgos c = (Commands.getSelectedAlgos)commands.getCom("get selected algos");
		c.execute();
		return c.getAlgosArr();
		
	}
	
	/**
	 * This function returns the description of some algorithm
	 * @param alg The name of algorithm by {@link String}
	 * @return The description by {@link String} of this algorithm
	 */
	public String getClassDisc(String alg)
	{
		return commands.getClassDiscription(alg);
	}
	
	/**
	 * This function starting the Initialization 
	 */
	public void startInitialization()
	{
		RunCommand rc = new RunCommand(commands.getCom("start init"));
		commands.getExecutor().execute(rc);
	}	
	
	/**
	 * This function stopping the Initialization
	 */
	public void stopInitialization()
	{
		RunCommand rc = new RunCommand(commands.getCom("stop init"));
		commands.getExecutor().execute(rc);
	}	
	
	/**
	 * This function pausing the Initialization
	 */
	public void pauseInitialization()
	{
		RunCommand rc = new RunCommand(commands.getCom("pause"));
		commands.getExecutor().execute(rc);
	}	
	
	/**
	 * This function resuming the Initialization
	 */
	public void resumeInitialization()
	{
		RunCommand rc = new RunCommand(commands.getCom("resume"));
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function loading the selected algorithms
	 * @param algs an {@link ArrayList} of the selected algorithms
	 */
	public void dynamicLoad(ArrayList<String> algs)
	{
		Commands.dynamicLoadingCommand c = (Commands.dynamicLoadingCommand)commands.getCom("load");
		c.setAlgosArr(algs);
		RunCommand rc = new RunCommand( c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function searching files by tags
	 * @param includedtags a {@link Set} of tags that included in tag's table of this file
	 * @param notIncludedtags a {@link Set} of tags that not included in tag's table of this file
	 * @return an {@link ArrayList} of the relevant files
	 */
	public ArrayList<String> searchByTag(Set<String> includedtags,Set<String> notIncludedtags)
	{
		Commands.searchByTagCommand c = (Commands.searchByTagCommand)commands.getCom("search by tag");
		c.setIncludedtags(includedtags);
		c.setNotIncludedtags(notIncludedtags);
		c.execute();
		return c.getFiles();
	}
	
	/**
	 * This function starting the listening
	 */
	public void startListening()
	{
		RunCommand rc = new RunCommand(commands.getCom("start"));
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function returns all the tags from DB
	 * @return an {@link ArrayList} of all the tags from DB
	 */
	public ArrayList<String> getAllTags()
	{
		Commands.getAllTagsCommand c = (Commands.getAllTagsCommand)commands.getCom("get tags");
		c.execute();
		return c.getTags();
	}
	
	/**
	 * This function returns all the regular expressions from DB
	 * @return an {@link ArrayList} of all the regular expressions from DB
	 */
	public ArrayList<String> getAllExpressions()
	{
		Commands.getAllExpressionsCommand c = (Commands.getAllExpressionsCommand)commands.getCom("get expressions");
		c.execute();
		return c.getExpressions();
	}
	
	/**
	 * This function stopping the listening
	 */
	public void stopListening()
	{
		RunCommand rc = new RunCommand(commands.getCom("stop"));
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function adding tag manually to selected file
	 * @param nameFile {@link String} the name of selected file
	 * @param tag {@link String} a new tag
	 * @param path {@link String} selected file's path
	 */
	public void addTag(String nameFile,String tag,String path)
	{
		Commands.addTagCommand c = (Commands.addTagCommand)commands.getCom("add tag");
		c.setFile(nameFile);
		c.setPathOnString(path);
		c.setTag(tag);
		RunCommand rc = new RunCommand( c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function removing tag manually to selected file
	 * @param nameFile {@link String} the name of selected file
	 * @param tag {@link String} a new tag
	 * @param path {@link String} selected file's path
	 */
	public void removeTag(String nameFile,String tag,String path)
	{
		Commands.deleteTagCommand c = (Commands.deleteTagCommand)commands.getCom("delete tag");
		c.setFile(nameFile);
		c.setPathOnString(path);
		c.setTag(tag);
		RunCommand rc = new RunCommand(c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function getting all the information from Log table 
	 * @return an {@link ArrayList} of the operations in the log
	 */
	public ArrayList<String> getLog()
	{
		Commands.getLogFile c = (Commands.getLogFile)commands.getCom("get log");
		c.execute();
		return c.getOpers();
	}	
	
	/**
	 * This function adding a directory to listening
	 * @param path the {@link Path} of selected directory
	 */
	public void selectDir(Path path)
	{
		Commands.selectDir c = (Commands.selectDir)commands.getCom("select dir");
		c.setPathOnString(path.toString());
		c.setPath(path);
		RunCommand rc = new RunCommand(c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function removing a directory from listening
	 * @param path {@link String}  the path of selected directory
	 */
	public void removeDir(String dir)
	{
		Commands.removeDir c = (Commands.removeDir)commands.getCom("remove dir");
		Path path = Paths.get(dir);
		c.setPathOnString(dir);
		c.setPath(path);
		c.setFlag(1);
		RunCommand rc = new RunCommand(c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function removing all the tags from {@link DataBase}
	 */
	public void cleanSystem()
	{
		Commands.cleanSystemCommand c = (Commands.cleanSystemCommand)commands.getCom("clean");
		RunCommand rc = new RunCommand(c);
		commands.getExecutor().execute(rc);
	}

	/**
	 * This function adding new expression to DB
	 * @param exp {@link String} the expression
	 */
	public void addExpression(String exp)
	{
		Commands.addExpressionCommand c = (Commands.addExpressionCommand)commands.getCom("add exp");
		c.setTag(exp);
		c.execute();
		//RunCommand rc = new RunCommand(c);
		//commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function assigning regular expressions to some directory for tagging
	 * @param exprs an {@link ArrayList} of the selected expressions
	 * @param path {@link String} the path of selected directory
	 */
	public void assignExpToDir(ArrayList<String> exprs,String path)
	{
		Commands.assignExpToDirCommand c = (Commands.assignExpToDirCommand)commands.getCom("assign");
		c.setExpressions(exprs);
		c.setPathOnString(path);
		RunCommand rc = new RunCommand(c);
		commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function removing an expression from DB
	 * @param exp {@link String} the expression
	 */
	public void removeExpression(String exp)
	{
		Commands.removeExpressionCommand c = (Commands.removeExpressionCommand)commands.getCom("remove exp");
		c.setExpression(exp);
		c.execute();
		//RunCommand rc = new RunCommand(c);
		//commands.getExecutor().execute(rc);
	}
	
	/**
	 * This function returns all listened directories from DB
	 * @return an {@link ArrayList} of all listened directories from DB
	 */
	public ArrayList<String> getDirectories()
	{
		Commands.getDirectoriesCommand c = (Commands.getDirectoriesCommand)commands.getCom("get directories");
		c.execute();
		return c.getDirs();
	}
	
	/**
	 * This function returns all tags of selected file
	 * @param file {@link String} a path of selected file 
	 * @return an {@link ArrayList} of file tags's
	 */
	public ArrayList<String> getTag(String file)
	{
		Commands.getTagCommand c = (Commands.getTagCommand)commands.getCom("get tag");
		c.setPathOnString(file);
		c.execute();
		return c.getArray();
	}
	
	/**
	 * This function returns the name of requested algorithm
	 * @param className {@link String} the name of the class (that implements the algorithm)
	 * @return {@link String} the name of algorithm
	 */
	public String getNameofAlgo(String className)
	{
		return commands.getNameofAlgo(className);
	}
	
}
